home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Milan_1991 / Devcon91.4 / AppShell / Examples / Timer / ticker.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  17.9 KB  |  656 lines

  1. /*
  2.  * ticker.c
  3.  *
  4.  * Test application for AppShell Timer Handler
  5.  * Written by John F Wiederhirn
  6.  *
  7.  * Based heavily on code in skeleton.c
  8.  * Copyright (C) 1991 Commodore-Amiga, Inc.
  9.  * Written by David N. Junod
  10.  *
  11.  */
  12.  
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <exec/libraries.h>
  16. #include <intuition/intuition.h>
  17. #include <graphics/gfx.h>
  18. #include <libraries/gadtools.h>
  19. #include <libraries/appshell.h>
  20. #include <utility/tagitem.h>
  21. #include <clib/alib_protos.h>
  22. #include <clib/alib_stdio_protos.h>
  23. #include <clib/exec_protos.h>
  24. #include <clib/intuition_protos.h>
  25. #include <clib/graphics_protos.h>
  26. #include <clib/gadtools_protos.h>
  27. #include <clib/appshell_protos.h>
  28. #include <clib/utility_protos.h>
  29. #include <pragmas/appshell.h>
  30. #include <string.h>
  31.  
  32. #include "timer.h"
  33. #include "ticker_rev.h"
  34.  
  35. /* The AppShell maintains some basic information on the application.  This
  36.  * information would appear in the About requester, and in AppExchange. */
  37. #define    APPBASE "TICKER"
  38. #define    APPNAME "Ticker"
  39. #define    APPVERS    VERS
  40. #define    APPCOPY "Copyright (C) 1991 Kompositor Software"
  41. #define    APPAUTH "John F Wiederhirn"
  42.  
  43. STRPTR ver = VERSTAG;
  44.  
  45. /* This structure contains all the data that our application will need.
  46.  * Change to suit your application. */
  47. struct AppData
  48. {
  49.     UBYTE ad_TmpText[128];    /* Temporary text buffer */
  50.     LONG ad_Mode;        /* Output mode */
  51. };
  52.  
  53. /* Each public function gets a numeric ID assigned to it.  You must
  54.  * assign an ID to each one of your functions.  Look at appshell.h for
  55.  * standard function ID's for things like New, Open, Cut, Copy, Paste,
  56.  * Quit, etc... */
  57. #define DUMMYID        APSH_USER_ID
  58. #define CInitID        (DUMMYID + 1L)
  59. #define    OpenMainID    (DUMMYID + 2L)
  60. #define    SetModeID    (DUMMYID + 3L)
  61. #define    ErrorID        (DUMMYID + 4L)
  62. #define TickID        (DUMMYID + 5L)
  63. #define BeepID        (DUMMYID + 6L)
  64. #define    GetInfoID    (DUMMYID + 7L)
  65. #define LAST_ID        (DUMMYID + 8L)
  66.  
  67.  
  68. /* These are the function prototypes for all the application implemented
  69.  * functions used in this example.  You must prototype all the functions
  70.  * that your application is going use in the function table. */
  71. VOID CInitFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  72. VOID OpenMainFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  73. VOID SetModeFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  74. VOID GetInfoFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  75. VOID ErrorFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  76. VOID TickFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  77. VOID BeepFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  78. VOID QuitFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  79.  
  80. /* The AppShell will convert this array into function table entries and will
  81.  * add them to the function table list.  Using the APSHF_PRIVATE flag, we are
  82.  * able to have functions that can't be triggered by the user.  This
  83.  * also defines the commands that are available through ARexx.  Note that
  84.  * the command parser is case-INSENSITIVE, but for readability, your
  85.  * entries in this table should follow standard capitalization rules. */
  86. struct Funcs FTable[] =
  87. {
  88.     {"Quit", QuitFunc, QuitID,},
  89.     {"Error", ErrorFunc, ErrorID,},
  90.  
  91.     // This is my baby...it handles incoming tick messages
  92.     {"Tick", TickFunc, TickID,},
  93.     {"Beep", BeepFunc, BeepID,},
  94.  
  95.  /* Functions with an argument template */
  96.     {"SetMode", SetModeFunc, SetModeID, "MALE/S,FEMALE/S,ZOMBIE/S", 3L, NULL,},
  97.     {"GetInfo", GetInfoFunc, GetInfoID, "STEM", 1L, NULL},
  98.  
  99.  /* These functions are private, and can not be accessed by the user */
  100.     {"CInit", CInitFunc, CInitID, NULL, NULL, APSHF_PRIVATE},
  101.     {"OpenMain", OpenMainFunc, OpenMainID, NULL, NULL, APSHF_PRIVATE},
  102.  
  103.  /* Marks the end of the array */
  104.     {NULL, NO_FUNCTION,}
  105. };
  106.  
  107. /* All text used in the application must be defined in a text array.  Then
  108.  * referred to by numeric ID. */
  109. STRPTR Def_Text[] =
  110. {
  111.  /* Padding */
  112.     "Written by John F Wiederhirn",
  113.  
  114.  /* Window title */
  115.     "The Ticker",
  116. #define    TEXT_TITLE    1
  117.  
  118.     "Sex:",
  119. #define    TEXT_LABEL    2
  120.  
  121.  /* Main window menus */
  122. #define    TEXT_MENU    3
  123.     " TITLE PROJECT  LABEL Project",
  124.     "  ITEM QUIT     LABEL Quit                 KEY Q CMD Quit",
  125.  
  126.     " TITLE EXTRAS   LABEL Extras",
  127.     "  ITEM ERROR    LABEL \"Show Error...\"    KEY , CMD Error",
  128.     "  ITEM CMDSHELL LABEL \"Command Shell...\" KEY . CMD CmdShell",
  129.  
  130.     "   END",
  131.  
  132.     "Error: %s",
  133. #define    ERROR_DISPLAY    9
  134.  
  135.     "Can't send stem variable",
  136. #define    ERROR_CANT_RVI    10
  137.  
  138.  /* NULL termination is required */
  139.     NULL
  140. };
  141.  
  142.  
  143. /* The following four tag arrays are GadTool tags for Window Environment
  144.  * objects. */
  145. STRPTR output_data[] =
  146. {
  147.     "Male",
  148.     "Female",
  149.     "Zombie",
  150.     NULL
  151. };
  152.  
  153. struct TagItem output_tags[] =
  154. {
  155.     {GTCY_Labels, (LONG) output_data},
  156.     {TAG_DONE,}
  157. };
  158.  
  159. /* These are the objects that are going to be within our main window.
  160.  * Note that the window itself is an object, and receives the SAME name
  161.  * as in the WindowEnvironment tag list, APSH_NameTag.  If you want
  162.  * to specify any window tags, attach them to the window object. */
  163. struct Object objects[] =
  164. {
  165.     {&objects[1], 0, 0, OBJ_Window, NULL, NULL, NULL, "Main", TEXT_TITLE,
  166.      {0, 0, 0, 0}, NULL,},
  167.  
  168.     {NULL, 0, 0, OBJ_Cycle, SetModeID, NULL, NULL, "Mode", TEXT_LABEL,
  169.      {44, 4, 101, 16}, output_tags,},
  170. };
  171.  
  172. /* This is a Window Environment tag list.  It describes a window. */
  173. struct TagItem mainenv[] =
  174. {
  175.     {APSH_NameTag, (ULONG) "Main"},
  176.     {APSH_Objects, (ULONG) objects},
  177.     {APSH_TTMenu, TEXT_MENU},
  178.     {APSH_WinAOpen, OpenMainID},
  179.     {APSH_RefreshData, OpenMainID},
  180.     {APSH_CloseWindow, QuitID},
  181.     {TAG_DONE,}
  182. };
  183.  
  184. /* Shared system libraries */
  185. extern struct Library *SysBase;
  186. extern struct Library *DOSBase;
  187. struct Library *GadToolsBase;
  188. struct Library *GfxBase;
  189. struct Library *IconBase;
  190. struct Library *IntuitionBase;
  191. struct Library *UtilityBase;
  192. struct Library *AppObjectsBase;
  193.  
  194. /* Library Environment:
  195.  * This tag array is used to open and close the shared system libraries
  196.  * needed by our application.
  197.  */
  198. struct TagItem Our_Libs[] =
  199. {
  200.  /* Minimum library version */
  201.     {APSH_LibVersion, 36L},
  202.  
  203.  /* All libraries are required */
  204.     {APSH_LibStatus, APSH_REQUIRED},
  205.  
  206.  /* Libraries to open */
  207.     {APSH_GadTools, (ULONG) & GadToolsBase},
  208.     {APSH_Gfx, (ULONG) & GfxBase},
  209.     {APSH_Icon, (ULONG) & IconBase},
  210.     {APSH_Intuition, (ULONG) & IntuitionBase},
  211.     {APSH_Utility, (ULONG) & UtilityBase},
  212.     {APSH_AppObjects, (ULONG) & AppObjectsBase},
  213.     {TAG_DONE,}
  214. };
  215.  
  216. /* Shell argument template */
  217. #define TEMPLATE "Male/S,Female/S,Zombie/S,PubScreen/K,PortName/K,Startup/K,NOGUI/S"
  218. #define OPT_MALE    0
  219. #define OPT_FEMALE    1
  220. #define    OPT_ZOMBIE    2
  221. #define    OPT_SCREENNAME    3
  222. #define    OPT_PORTNAME    4
  223. #define    OPT_STARTUP    5
  224. #define    OPT_NOGUI    6
  225. #define OPT_COUNT    7
  226.  
  227.  /* ARexx user interface environment specification array */
  228. struct TagItem Handle_AREXX[] =
  229. {
  230.     {APSH_Extens, (ULONG) "skel"},
  231.     {APSH_Rating, APSH_OPTIONAL},
  232.     {TAG_DONE,}
  233. };
  234.  
  235.  /* Command Shell user interface environment specification array */
  236. struct TagItem Handle_DOS[] =
  237. {
  238.  
  239.  /*
  240.   * Presence of this tag, makes the Command Shell to stay closed until the user
  241.   * sends a CMDSHELL OPEN command.
  242.   */
  243.     {APSH_Status, APSHP_INACTIVE},
  244.     {APSH_Rating, APSH_REQUIRED},
  245.     {TAG_DONE,}
  246. };
  247.  
  248. /* These tags describe the Intuition user interface. */
  249. struct TagItem Handle_IDCMP[] =
  250. {
  251.     {APSH_Rating, APSH_REQUIRED},
  252.     {TAG_DONE,}
  253. };
  254.  
  255. /* These tags describe the Simple IPC user interface. */
  256. struct TagItem Handle_SIPC[] =
  257. {
  258.     {APSH_Rating, APSH_REQUIRED},
  259.     {TAG_DONE,}
  260. };
  261.  
  262. // FOR TIMER HANDLER
  263. //
  264. // This declares the delay value.
  265. // Extend it if you need more time before it all blows up.
  266. //
  267.  
  268. /* This is a timer test */
  269. struct TagItem Handle_TIMER[] =
  270. {
  271.     {APSH_Setup, setup_timerA},
  272.     {APSH_Rating, APSH_REQUIRED},
  273.     {APSH_Status, APSHP_INACTIVE},
  274.     {TAG_DONE,}
  275. };
  276.  
  277. /* Application Environment:
  278.  * Tell about our application */
  279. struct TagItem Our_App[] =
  280. {
  281.  /* About the application */
  282.     {APSH_AppName, (ULONG) APPNAME},
  283.     {APSH_AppVersion, (ULONG) APPVERS},
  284.     {APSH_AppCopyright, (ULONG) APPCOPY},
  285.     {APSH_AppAuthor, (ULONG) APPAUTH},
  286.  
  287.  /* Trigger the library opening module */
  288.     {APSH_OpenLibraries, (ULONG) Our_Libs},
  289.  
  290.  /* Specify the application function table */
  291.     {APSH_FuncTable, (ULONG) FTable},
  292.  
  293.  /* Specify the application text table */
  294.     {APSH_DefText, (ULONG) Def_Text},
  295.  
  296.  /* Tell how memory we need for our own data */
  297.     {APSH_UserDataSize, sizeof (struct AppData)},
  298.  
  299.  /* Give our Shell startup argument template */
  300.     {APSH_Template, (ULONG) TEMPLATE},
  301.     {APSH_NumOpts, (ULONG) OPT_COUNT},
  302.  
  303.  /* Must always specify the SIPC user interface */
  304.     {APSH_AddSIPC_UI, (ULONG) Handle_SIPC},
  305.  
  306.  /* Add an ARexx user interface */
  307.     {APSH_AddARexx_UI, (ULONG) Handle_AREXX},
  308.  
  309.  /* Add a Command Shell user interface */
  310.     {APSH_AddCmdShell_UI, (ULONG) Handle_DOS},
  311.  
  312.  /* Add an Intuition user interface */
  313.     {APSH_AddIntui_UI, (ULONG) Handle_IDCMP},
  314.  
  315.  /* Add a custom handler (timer) */
  316.     {APSH_AddHandler, (ULONG) Handle_TIMER},
  317.  
  318.  /* Specify a custom initialization routine */
  319.     {APSH_AppInit, CInitID},
  320.  
  321.     {TAG_DONE,}
  322. };
  323.  
  324. extern struct Library *AppShellBase;
  325.  
  326. /* Sample initialization function */
  327. VOID CInitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  328. {
  329.     extern struct TagItem mainenv[];
  330.     struct AppData *ad = ai->ai_UserData;
  331.     struct timeval tval5 = {5L, 0L};
  332.     struct timeval tval1 = {1L, 0L};
  333.  
  334.     /* See if any Shell arguments were specified */
  335.     if (ai->ai_Options[OPT_MALE])
  336.     {
  337.     ad->ad_Mode = 0L;
  338.     }
  339.     else if (ai->ai_Options[OPT_FEMALE])
  340.     {
  341.     ad->ad_Mode = 1L;
  342.     }
  343.     else if (ai->ai_Options[OPT_ZOMBIE])
  344.     {
  345.     ad->ad_Mode = 2L;
  346.     }
  347.  
  348.     /* Open the Main window */
  349.     HandlerFunc (ai,
  350.         APSH_Handler, "IDCMP",
  351.         APSH_Command, APSH_MH_OPEN,
  352.         APSH_WindowEnv, (ULONG) mainenv,
  353.         TAG_DONE);
  354.  
  355.     /* Here we start the timer ticking */
  356.     HandlerFunc (ai,
  357.         APSH_Handler,    "TIMER",        // Us
  358.         APSH_Command,    APSH_MH_OPEN,        // Open us
  359.         APSH_TimerMode,    TH_TICKING,        // Open us ticking
  360.         APSH_TimerLen,    (ULONG) &tval5,        // Open us ticking for so long
  361.         APSH_NameTag,    (ULONG) "Ticker5",    // and take our name.
  362.         APSH_CmdID,    TickID,            // Wake me when its over...
  363.         TAG_DONE);
  364.  
  365.     /* Here we start the timer ticking */
  366.     HandlerFunc (ai,
  367.         APSH_Handler,    "TIMER",        // Us
  368.         APSH_Command,    APSH_MH_OPEN,        // Open us
  369.         APSH_TimerMode,    TH_TICKING,        // Open us ticking
  370.         APSH_TimerLen,    (ULONG) &tval1,        // Open us ticking for so long
  371.         APSH_NameTag,    (ULONG) "Ticker1",    // and take our name.
  372.         APSH_CmdID,    BeepID,            // Wake me when its over...
  373.         TAG_DONE);
  374. }
  375.  
  376. //
  377. // If the dratted thing ever got this far, it should tick and switch from
  378. // Male->Female->Zombie every n seconds as set in the timeval structure.
  379. // Worked fine in the single-threaded one, here it doesnt even get this far.
  380. //
  381. VOID TickFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  382. {
  383.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  384.     struct Gadget *gad;
  385.     struct Window *win;
  386.     LONG mode = (-1);
  387.  
  388.     mode = ++ad->ad_Mode;
  389.     if ((ad->ad_Mode)>2)
  390.     ad->ad_Mode = mode = 0;
  391.  
  392.     /* Update the gadget */
  393.     if ((mode >= 0) &&
  394.     (APSHGetGadgetInfo (ai, "Main", "Mode", (ULONG *) & win, (ULONG *) & gad)))
  395.     {
  396.     /* Update the string gadget */
  397.     GT_SetGadgetAttrs (gad, win, NULL, GTCY_Active, mode, TAG_DONE);
  398.     }
  399.  
  400. }
  401.  
  402. /* Just to show you that there can be multiple events occurring... */
  403. VOID BeepFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  404. {
  405.     DisplayBeep (NULL);
  406. }
  407.  
  408. /* This function is called every time the Main window is opened.  It
  409.  * was specified by using the APSH_WinAOpen tag in the Main Window
  410.  * Environemt tag array.  I'm also 'cheating' and calling it everytime
  411.  * I want to refresh the window and graphics. */
  412.  
  413. VOID OpenMainFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  414. {
  415.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  416.     struct Window *win;
  417.     struct Gadget *gad;
  418.  
  419.     /* Update the mode gadget */
  420.     if (APSHGetGadgetInfo (ai, "Main", "Mode", (ULONG *) & win, (ULONG *) & gad))
  421.     {
  422.     /* Update the string gadget */
  423.     GT_SetGadgetAttrs (gad, win, NULL, GTCY_Active, ad->ad_Mode, TAG_DONE);
  424.     }
  425. }
  426.  
  427. VOID SetModeFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  428. {
  429.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  430.     struct TagItem *attrs = af->af_Attrs;
  431.     struct TagItem *tag;
  432.     struct Gadget *gad;
  433.     struct Window *win;
  434.     LONG mode = (-1);
  435.     struct Funcs *f;
  436.  
  437.     if (f = af->af_FE)
  438.     {
  439.     if (f->fe_Options[0])
  440.     {
  441.         ad->ad_Mode = mode = 0;
  442.     }
  443.     else if (f->fe_Options[1])
  444.     {
  445.         ad->ad_Mode = mode = 1;
  446.     }
  447.     else if (f->fe_Options[2])
  448.     {
  449.         ad->ad_Mode = mode = 2;
  450.     }
  451.     }
  452.     /* Being set from the gadget */
  453.     else if (tag = FindTagItem (APSH_MsgCode, attrs))
  454.     {
  455.     ad->ad_Mode = tag->ti_Data;
  456.     }
  457.  
  458.     /* Update the gadget */
  459.     if ((mode >= 0) &&
  460.     (APSHGetGadgetInfo (ai, "Main", "Mode", (ULONG *) & win, (ULONG *) & gad)))
  461.     {
  462.     /* Update the string gadget */
  463.     GT_SetGadgetAttrs (gad, win, NULL, GTCY_Active, mode, TAG_DONE);
  464.     }
  465. }
  466.  
  467.  /* sample function returning an error */
  468. VOID ErrorFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  469. {
  470.     STRPTR name = "Uh Oh!";
  471.  
  472.     /* sample error return */
  473.     ai->ai_Pri_Ret = RETURN_ERROR;
  474.     ai->ai_Sec_Ret = ERROR_DISPLAY;
  475.     ai->ai_TextRtn = PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, (int) name);
  476. }
  477.  
  478. /* Given a screen pointer, determine the public screen name */
  479. VOID PubScreenName (struct Screen * scr, STRPTR buffer)
  480. {
  481.     struct Screen *cs = NULL;
  482.     struct List *publist;
  483.     struct List copy_publist;
  484.     struct PubScreenNode *psnode;
  485.     struct PubScreenNode *copy_psnode;
  486.  
  487.     /* Initialize our variables */
  488.     strcpy (buffer, "<private>");
  489.     NewList (©_publist);
  490.  
  491.     /* Lock the public screen list */
  492.     publist = LockPubScreenList ();
  493.  
  494.     /* and copy it */
  495.     for (psnode = (struct PubScreenNode *) publist->lh_Head;
  496.      psnode->psn_Node.ln_Succ;
  497.      psnode = (struct PubScreenNode *) psnode->psn_Node.ln_Succ)
  498.     {
  499.     if (copy_psnode = AllocMem (sizeof (struct PubScreenNode), MEMF_CLEAR))
  500.     {
  501.         /* Copy the structure */
  502.         *copy_psnode = *psnode;
  503.  
  504.         /*
  505.          * ln_Name points to the public screen name, make your own copy
  506.          */
  507.         if (copy_psnode->psn_Node.ln_Name = AllocMem (strlen (psnode->psn_Node.ln_Name) + 1, MEMF_CLEAR))
  508.         {
  509.         strcpy (copy_psnode->psn_Node.ln_Name, psnode->psn_Node.ln_Name);
  510.         }
  511.  
  512.         AddTail (©_publist, (struct Node *) copy_psnode);
  513.     }
  514.     }
  515.  
  516.     UnlockPubScreenList ();
  517.  
  518.     psnode = (struct PubScreenNode *) copy_publist.lh_Head;
  519.     while ((copy_psnode = (struct PubScreenNode *) psnode->psn_Node.ln_Succ) &&
  520.        (cs == NULL))
  521.     {
  522.     if (psnode->psn_Screen == scr)
  523.     {
  524.         strcpy (buffer, psnode->psn_Node.ln_Name);
  525.         cs = psnode->psn_Screen;
  526.     }
  527.  
  528.     if (psnode->psn_Node.ln_Name)
  529.     {
  530.         FreeMem (psnode->psn_Node.ln_Name, strlen (psnode->psn_Node.ln_Name) + 1);
  531.     }
  532.     Remove ((struct Node *) psnode);
  533.     FreeMem (psnode, sizeof (struct PubScreenNode));
  534.     psnode = copy_psnode;
  535.     }
  536. }
  537.  
  538. /* sample function returning ARexx stem variables */
  539. VOID GetInfoFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  540. {
  541.     /* ARexx function prototypes */
  542.     extern LONG SetRexxVar (struct RexxMsg *, UBYTE *, UBYTE *, LONG);
  543.     extern LONG CheckRexxMsg (struct RexxMsg *);
  544.  
  545.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  546.     UBYTE stem[128], value[140];
  547.     struct MsgHandler *mh;
  548.     struct RexxMsg *msg;
  549.     struct Funcs *f;
  550.     LONG kind;
  551.  
  552.     /* Build error string */
  553.     ai->ai_Pri_Ret = RETURN_WARN;
  554.     ai->ai_Sec_Ret = ERROR_CANT_RVI;
  555.     ai->ai_TextRtn = PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
  556.  
  557.     /* Find out what type the current message is */
  558.     if (GetAPSHAttr (ai, APSH_ActvMH, ai, &kind))
  559.     {
  560.     /* See if the current message is an ARexx message */
  561.     if (kind == APSH_AREXX_ID)
  562.     {
  563.         /* Get a pointer to the current message */
  564.         if (GetAPSHAttr (ai, APSH_ActvMessage, ai, &msg))
  565.         {
  566.         /* Check to see if we can set an RVI on this message. */
  567.         if (CheckRexxMsg (msg))
  568.         {
  569.             /* Get the destination stem name */
  570.             sprintf (stem, "%s.", ai->ai_BaseName);
  571.             if (f = af->af_FE)
  572.             {
  573.             if (f->fe_Options[0])
  574.             {
  575.                 strcpy (stem, (STRPTR) f->fe_Options[0]);
  576.             }
  577.             }
  578.  
  579.         /* Send the application version */
  580.  
  581.             /* Build the version variable */
  582.             sprintf (ad->ad_TmpText, "%sVERSION", stem);
  583.             strcpy (value, ai->ai_AppVersion);
  584.  
  585.             /* Set the RVI's */
  586.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  587.  
  588.         /* Send the current public screen name */
  589.  
  590.             /* Build the screen name variable */
  591.             value[0] = 0;
  592.             sprintf (ad->ad_TmpText, "%sSCREEN", stem);
  593.             if (ai->ai_ScreenName)
  594.             {
  595.             strcpy (value, ai->ai_ScreenName);
  596.             }
  597.             else
  598.             {
  599.             PubScreenName (ai->ai_Screen, value);
  600.             }
  601.  
  602.             /* Set the RVI's */
  603.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  604.  
  605.         /* Send the ARexx port name */
  606.  
  607.             /* Build the ARexx port name variable */
  608.             sprintf (ad->ad_TmpText, "%sAREXX", stem);
  609.  
  610.             /* Build the value string */
  611.             strcpy (value, "<unnamed>");
  612.             if (GetAPSHAttr (ai, APSH_ARexxMH, ai, &mh) && mh)
  613.             {
  614.             strcpy (value, mh->mh_PortName);
  615.             }
  616.  
  617.             /* Set the RVI's */
  618.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  619.  
  620.         /* Send the current mode */
  621.  
  622.             /* Build the variable name */
  623.             sprintf (ad->ad_TmpText, "%sMODE", stem);
  624.  
  625.             /* Build the value string */
  626.             strcpy (value, "<unset>");
  627.             if (ad->ad_Mode == 0)
  628.             strcpy (value, "Male");
  629.             else if (ad->ad_Mode == 1)
  630.             strcpy (value, "Female");
  631.             else if (ad->ad_Mode == 2)
  632.             strcpy (value, "Zombie");
  633.  
  634.             /* Set the RVI's */
  635.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  636.  
  637.         /* Return the name of the destination stem variable */
  638.  
  639.             /* Let them know what the stem variable is named */
  640.             strcpy (ad->ad_TmpText, stem);
  641.             ai->ai_Pri_Ret = RETURN_OK;
  642.             ai->ai_Sec_Ret = NULL;
  643.             ai->ai_TextRtn = ad->ad_TmpText;
  644.         }
  645.         }
  646.     }
  647.     }
  648. }
  649.  
  650.  /* Shutdown routine */
  651. VOID QuitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  652. {
  653.     /* Tell the AppShell that we're all done now. */
  654.     ai->ai_Done = TRUE;
  655. }
  656.